package com.API.beans;

import com.API.dal.entities.*;
import com.API.dal.entities.Objects;
import com.API.dal.providers.CostsProvider;
import com.API.dal.providers.EmployeesProvider;
import com.API.dal.providers.ProjectProvider;
import com.API.dal.providers.SalaryProvider;
import org.primefaces.context.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import java.math.BigDecimal;
import java.util.*;

/**
 * Класс отвечающий за предоставление данных primeFaces сервлетам через spring
 * интеграцию
 */
@Component
@Scope("request")
public class EmployeesBean {


    @Autowired
    EmployeesProvider employeesProvider;
    @Autowired
    SalaryProvider salaryProvider;
    @Autowired
    CostsProvider costsProvider;
    @Autowired
    ProjectProvider projectProvider;

    List<Employees> employeesList;
    Employees employee;
    Employees selectedEmployee;
    Costs costs;
    EmployeeProject employeeProject;


    public EmployeesBean(){
        employee = new Employees();
        SalaryType st = new SalaryType();
        Posts ps = new Posts();
        costs = new Costs();
        employee.setPosts(ps);
        employee.setSalaryType(st);
        employeeProject = new EmployeeProject(new EmployeeProjectId(),
                new Employees(), new Objects());


    }

    public Costs getCosts() {
        return costs;
    }

    public void setCosts(Costs costs) {
        this.costs = costs;
    }

    public void setEmployeeProject(EmployeeProject employeeProject) {
        this.employeeProject = employeeProject;
    }

    public EmployeeProject getEmployeeProject() {
        return employeeProject;
    }

    //Список всех сотрудников
    public List<Employees> getEmployeesList() {
        if (employeesList == null)
            employeesList = employeesProvider.getEmployees();
        for (Employees emp: employeesList){
            int id = emp.getSalaryType().getId();
            emp.setSalaryType(salaryProvider.getSalaryTypeById(id));
            emp.setPosts(employeesProvider.getPostById(emp.getPosts().getId()));
        }
        return employeesList;
    }


    //метод для AutoComplete
    public List<String> gelCompleteEmployee(String query){
        List<String> completeList = new LinkedList<String>();
        String employeeName;
        List<Employees> empList = employeesProvider.getEmployees();
        for(Employees emp: empList){
            employeeName = emp.getName();
            if (employeeName.contains(query.toUpperCase()) || employeeName.contains(query.toLowerCase())
                    || employeeName.contains(query))
                completeList.add(employeeName);
        }
        return completeList;
    }
    public Employees getEmployee() {
        return employee;
    }

    public void setEmployee(Employees employee) {
        this.employee = employee;
    }

    public Employees getSelectedEmployee() {
        return selectedEmployee;
    }

    public void setSelectedEmployee(Employees selectedEmployee) {
        this.selectedEmployee = selectedEmployee;
    }

    public List<String> getPosts(){
        List<String> postList = new LinkedList<String>();
        for (Posts pst : employeesProvider.getPosts())
            postList.add(pst.getName());
        return postList;
    }


    public List<String> getCostsTypes(){
        List<String> ctl = new LinkedList<String>();
        for (CostsTypes ct: costsProvider.getCostsTypes())
            ctl.add(ct.getName());
        return ctl;
    }



    public String getDept(int employee_id){

        return "0";
    }

    //Добавить сотрудника
    public void addEmployee(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.execute("addEmployeeDialog.show()");
    }
    //Редактировать сотрудника
    public void editEmployee(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.update("employeeForm");
        if (selectedEmployee != null){
            selectedEmployee = employeesProvider.getEmployeeById(selectedEmployee.getId());
            selectedEmployee.setSalaryType(salaryProvider.getSalaryTypeById(selectedEmployee.getSalaryType().getId()));
            selectedEmployee.setPosts(employeesProvider.getPostById(selectedEmployee.getPosts().getId()));
            context.execute("editEmployeeDialog.show()");
        }
        else {
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Ошибка.","Сотрудник не выбран");
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }

    }

    public void saveEdit(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.update("employeeForm");
        employeesProvider.updateEmployee(selectedEmployee);
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Сотрудник изменен успешно.", employee.getName());
        FacesContext.getCurrentInstance().addMessage(null, msg);
        context.addCallbackParam("saveEditEmployee", true);

    }

    public void closeEdit(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.execute("editEmployeeDialog.save()");
    }
    //Добавляем расходы
    public void addExpense(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.execute("addEmployeeDialogExpense.show()");

    }



    public void saveExpense(){
        RequestContext context = RequestContext.getCurrentInstance();
        context.update("employeeForm");
        Employees  emp = employeesProvider.getEmployeesByName(
                employeeProject.getEmployees().getName()).get(0);
        Objects pr = projectProvider.getProjectByName(employeeProject.getObjects().getName());
        employeeProject.setEmployees(emp);
        employeeProject.setObjects(pr);
        employeeProject.getId().setTotal(new BigDecimal(employeeProject.getId().getQuantity() * emp.getSalary()));
        employeeProject.getId().setProjectId(pr.getId());
        employeeProject.getId().setEmployeeId(emp.getId());
        employeesProvider.addEmployeeProjectWork(employeeProject);
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Затраты добавленны успешно.", employee.getName());
        FacesContext.getCurrentInstance().addMessage(null, msg);
        context.addCallbackParam("saveEmployeeExpense", true);
    }

    public void viewEmployee(){

    }

    //Метод автозавершения типа ставки
    public List<String> getSalaryType(){
        List<String> completeList = new LinkedList<String>();
        for(SalaryType salary: salaryProvider.getSalaryTypes()){
            String str = salary.getName();
            completeList.add(str);
        }
        return completeList;
    }

    public void saveEmployee() {
        RequestContext context = RequestContext.getCurrentInstance();
        context.update("employeeForm");
        String str = employee.getSalaryType().getName();
        SalaryType salaryType = salaryProvider.getSalaryTypeByName(str);
        str = employee.getPosts().getName();
        Posts post = employeesProvider.getPostByName(str);
        employee.setPosts(post);
        employee.setSalaryType(salaryType);
        employeesProvider.addEmployee(employee);
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Employee added successfully", employee.getName());
        FacesContext.getCurrentInstance().addMessage(null, msg);
        context.addCallbackParam("saveEmployee", true);
    }

    public void showDebit(){
        final RequestContext context = RequestContext.getCurrentInstance();
        context.execute("debitEmployeeDialog.show()");
    }

    public void debit(){
        RequestContext context = RequestContext.getCurrentInstance();
        context.update("employeeForm");
        debitSave();

        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Зарплата сотруднику списана.", employee.getName());
        FacesContext.getCurrentInstance().addMessage(null, msg);
        context.addCallbackParam("saveEmployeeDebit", true);

    }

    private void debitSave(){
        Map<Objects,BigDecimal> mp = debitProjects(employee.getName());
        Set<Objects> sp = mp.keySet();
        Iterator<Objects> isp = sp.iterator();
        CostsTypes ct = costsProvider.getCostTypeByName("Заработная плата");
        double total = 0;
        while (isp.hasNext()){
            Objects object = isp.next();
            BigDecimal sum = mp.get(object);
            total = total - sum.doubleValue();
            String str = "Заработная плата по проекту " + object.getName()
                    + " для сотрудника " + employee.getName();
            Costs cs = new Costs(ct, costs.getChangeDate(), sum);
            cs.setNotes(str);
            costsProvider.addCost(cs);
            EmployeesCosts ec = new EmployeesCosts();
            ProjectsCosts pc = new ProjectsCosts();
            ec.setId(new EmployeesCostsId(employee.getId(), cs.getId()));
            pc.setId(new ProjectsCostsId(object.getId(), cs.getId()));
            ec.setEmployees(employee);
            ec.setCosts(cs);
            pc.setObjects(object);
            pc.setCosts(cs);
            employeesProvider.addEmployeeCost(ec);
            projectProvider.addProjectCost(pc);
            EmployeeProject ep = new EmployeeProject(new EmployeeProjectId(), employee, object);
            ep.getId().setTotal(BigDecimal.valueOf(total));
            ep.getId().setEmployeeId(employee.getId());
            ep.getId().setProjectId(object.getId());
            ep.getId().setWorkDate(costs.getChangeDate());
            employeesProvider.addEmployeeProjectWork(ep);
        }



    }

    private Map<Objects,BigDecimal> debitProjects(String employee_name){
        List<EmployeeProject> employeeProjectList = employeesProvider.getEmployeeProjects(
                employee_name);
        Map<Objects,BigDecimal>  projectCost = new HashMap<Objects, BigDecimal>();
        for (EmployeeProject ep: employeeProjectList){
            ep.setObjects(projectProvider.getProjectById(ep.getId().getProjectId()));
            if (!projectCost.containsKey(ep.getObjects())) {
                projectCost.put(ep.getObjects(), new BigDecimal(0));
            }
            else {
                double bs = projectCost.get(ep.getObjects()).doubleValue() +
                        ep.getId().getTotal().doubleValue();
                projectCost.remove(ep.getObjects());
                projectCost.put(ep.getObjects(), BigDecimal.valueOf(bs));

            }
        }
        return projectCost;
    }



    public void closeDebit(){
        final RequestContext context= RequestContext.getCurrentInstance();
        context.execute("debitEmployeeDialog.hide()");
    }
}
